home *** CD-ROM | disk | FTP | other *** search
Text File | 1999-04-13 | 48.4 KB | 1,657 lines | [TEXT/ALFA] |
- ## -*-Tcl-*-
- # ###################################################################
- # Vince's Additions - an extension package for Alpha
- #
- # FILE: "filesetsMenu.tcl"
- # created: 20/7/96 {6:22:25 pm}
- # last update: 13/4/1999 {8:24:03 pm}
- # Author: Vince Darley
- # E-mail: <darley@fas.harvard.edu>
- # mail: Division of Applied Sciences, Harvard University
- # Oxford Street, Cambridge MA 02138, USA
- # www: <http://www.fas.harvard.edu/~darley/>
- #
- #==============================================================================
- # Alpha calls two fileset-related routines, 'getCurrFileSet', and
- # 'getFileSetNames'. Alpha will also attempt to set the variable 'currFileSet'
- # on occasion, but this isn't critical.
- #==============================================================================
- #
- # modified by rev reason
- # -------- --- --- -----------
- # 24/3/96 VMD 1.0 update of Pete's original to allow mode-specific filesets
- # 27/3/96 VMD 1.1 added hierarchial filesets, and checks for unique menus
- # 13/6/96 VMD 1.2 memory efficiency improvements with 'fileSets' array
- # 10/3/97 VMD 1.3 added 'procedural' fsets, including 'Open Windows'
- # 6/4/97 VMD 1.31 various fixes incorporated - thanks!
- # 11/7/97 VMD 1.4 added cache for the fileset menu, improved wc proc.
- # 15/7/97 VMD 1.41 better handling of out-of-date filesets, and dir opening
- # 15/7/97 VMD 1.42 placed cache in separate file.
- # 21/7/97 VMD 1.43 added glob patterns to ignore for directory filesets
- # 22/7/97 VMD 1.5 more sophisticated menu caching. No more long rebuilds!
- # 10/9/97 VMD 1.6 simplified some stuff for new Alpha-Tcl
- # 7/12/97 VMD 1.6.1 makes use of winNumDirty flag
- # 12/1/98 VMD 1.6.2 removes special treatment of *recent*
- # 15/1/1999 VMD 1.7.2 a year of improvements....
- # ###################################################################
- ##
-
- ##
- # These procedures are now more robust and general-purpose. Basic new
- # features are:
- #
- # * user configurable menu * unique-menu names are ensured, so there can
- # be no clashes * new fileset types ('tex' and 'fromHierarchy') * new
- # utility functions ('stuff', 'wordCount',...) * filesets need not
- # appear in the menu; in fact they can be anywhere you like
- #
- # Known Bugs:
- #
- # You cannot have a hierarchial fileset which contains more than one
- # folder with the same name as the fileset, including the base folder.
- # This is very hard to fix, and the easy workaround is just to rename the
- # fileset in some minor way.
- ##
-
- alpha::menu filesetMenu 1.7.5 global "•131" {
- } {filesetMenu} {} uninstall {this-file} help {[editMark [file join $HOME Help "Alpha Manual"] "File Sets" -r]}
-
- proc filesetMenu {} {}
-
- # Build some filesets on the fly.
- set gfileSets(Help) [file join $HOME Help *]
- set gfileSets(System) [list [file join $HOME Tcl SystemCode *.tcl] 2]
- set gfileSets(Menus) [list [file join $HOME Tcl Menus *.tcl] 2]
- set gfileSets(Modes) [list [file join $HOME Tcl Modes *.tcl] 2]
-
- # Declare their types
- set gfileSetsType(Help) "fromDirectory"
- set gfileSetsType(System) "fromHierarchy"
- set gfileSetsType(Modes) "fromHierarchy"
- set gfileSetsType(Menus) "fromHierarchy"
-
- proc filesetRegisterProcedural {name proc} {
- global gfileSets gfileSetsType
- set gfileSets($name) $proc
- set gfileSetsType($name) "procedural"
- }
-
- filesetRegisterProcedural "Open Windows" procFilesetOpenWindows
- filesetRegisterProcedural "Top Window's Folder" procFilesetDirTopWin
- filesetRegisterProcedural "Recurse in folder…" procFilesetRecurseIn
-
- # Procs for procedural filesets
- proc procFilesetRecurseIn {} {
- return [file::recurse [get_directory -p "Search recursively in which folder?"]]
- }
-
- proc procFilesetOpenWindows {} { return [winNames -f] }
- proc procFilesetDirTopWin {} {
- if {[set w [win::Current]] == ""} {
- return ""
- } else {
- return [glob -t TEXT -nocomplain [file join [file dirname [win::Current]] *]]
- }
- }
-
- if {![file exists [file join $HOME Tcl Packages]]} { file mkdir [file join $HOME Tcl Packages] }
- set gfileSets(Packages) [list [file join $HOME Tcl Packages *.tcl] 2]
- set gfileSetsType(Packages) "fromHierarchy"
-
- lunion varPrefs(Files) currFileSet
- # Default curr fileset is the first one.
- newPref var currFileSet "System" global changeFileSet gfileSets array
-
- # ◊◊◊◊ Variables and flags ◊◊◊◊ #
-
- #################################################
- # Any of these can be over-ridden by the stored #
- # definitions in defs.tcl, arrdefs.tcl #
- #################################################
-
- ##
- # We don't show the 'help' fileset, since it's under the MacOS AppleGuide
- # menu. Also we could perhaps yank tex-filesets away into their own menu,
- # in which case the tex-system could add to this variable as it went
- # along.
- ##
- lunion filesetsNotInMenu "Help" "Open Windows" "Top Window's Folder" \
- "Recurse in folder…"
-
- ##
- # A type is a means of generating a fileset given its
- # description in the variable 'gfileSets(name)':
- ##
- lunion fileSetsTypes "list" "glob" "fromHierarchy" "procedural"
-
- ##
- # A menu type is a means of prompting the user and characterising the
- # interface to a type, even though the actual storage may be very simple
- # (a list in most cases).
- ##
- set fileSetsTypesThing(fromDirectory) "glob"
- set fileSetsTypesThing(fromHierarchy) "fromHierarchy"
- set fileSetsTypesThing(think) "list"
- set fileSetsTypesThing(codewarrior) "list"
- set fileSetsTypesThing(ftp) "list"
- set fileSetsTypesThing(fromOpenWindows) "list"
- set fileSetsTypesThing(procedural) "procedural"
-
- ##
- # To add a new fileset type, you need to define the following:
- # set fileSetsTypesThing(myType) "list"
- # proc myTypeCreateFileset {} {}
- # proc myTypeFilesetUpdate {name} {}
- #
- # For more complex types (e.g. the tex-type), define as follows:
- # set fileSetsTypesThing(myType) "myType"
- # proc myTypeCreateFileset {} {}
- # proc myTypeFilesetSelected { fset menu item } {}
- # proc myTypeFilesetUpdate { name } {}
- # proc myTypeListFilesInFileset { name } {}
- # proc myTypeMakeFileSetSubMenu { name } {}
- #
- # These procedures will all be called automatically under the correct
- # circumstances. The purposes of these are as follows:
- #
- # 'create' -- query the user for name etc. and create
- # 'update' -- given the information in 'gfileSets', recalculate
- # the member files.
- # 'selected' -- a member was selected in a menu.
- # 'list' -- given info in all except 'fileSets', return list
- # of files to be stored in that variable.
- # 'submenu' -- generate the sub-menu
- #
- # Your code may wish to call 'isWindowInFileset ?win? ?type?' to check
- # if a given (current by default) window is in a fileset of a given type.
- ##
-
- ##
- # -------------------------------------------------------------------------
- #
- # "filesetSortOrder" --
- #
- # The structure of this variable dictates how the fileset menu is
- # structured:
- #
- # '{pattern p}'
- # lists all filesets which match 'p'
- # '-'
- # adds a separator line
- # '{list of types}'
- # lists all filesets of those types.
- # '{submenu name sub-order-list}'
- # adds a submenu with name 'name' and recursively
- # adds filesets to that submenu as given by the
- # sub-order.
- #
- # Leading, trailing and double separators are automatically
- # removed.
- #
- # -------------------------------------------------------------------------
- ##
- ensureset filesetSortOrder { {pattern *System} {pattern Packages} \
- {pattern Menus} {pattern Modes} {pattern Preferences} \
- - {tex} - {pattern *.cc} {submenu Headers {pattern *.h}} \
- - {fromDirectory think codewarrior ftp \
- fromOpenWindows fromHierarchy} * }
-
- set "filesetUtils(browseFileset…)" [list * browseFileset]
- set "filesetUtils(renameFileset…)" [list * renameFileset]
- set "filesetUtils(openEntireFileset…)" [list * openEntireFileset]
- set "filesetUtils(filesetToAlpha…)" [list * filesetToAlpha]
- set "filesetUtils(closeEntireFileset…)" [list * closeEntireFileset]
- set "filesetUtils(replaceInFileset…)" [list * replaceInFileset]
- set "filesetUtils(stuffFileset…)" [list * stuffFileset]
- set "filesetUtils(wordCount)" [list * wordCountFileset]
- set "filesetUtils(openFilesetFolder…)" [list * openFilesetFolder]
-
-
- ##
- # The meaning of these flags is as follows:
- # sortFilesetItems --
- # a type can have the option of being unsorted (e.g. tex-filesets)
- # indentFilesetItems --
- # visual formatting may be of relevance to some types
- # sortFilesetsByType --
- # use the variable 'filesetSortOrder' to determine the
- # visual structure of the fileset menu
- # autoAdjustFileset --
- # when a file is selected from the menu, do we try and
- # keep 'currFileSet' accurate?
- # includeNonTextFiles --
- # filesets may include non-text files. Alpha will tell the
- # finder to open these if they are selected.
- ##
- newPref flag sortFilesetItems 0 "fileset"
- newPref flag indentFilesetItems 0 "fileset"
- newPref flag sortFilesetsByType 0 "fileset" rebuildSomeFilesetMenu
- newPref flag autoAdjustFileset 1 "fileset"
- newPref flag includeNonTextFiles 0 "fileset" rebuildSomeFilesetMenu
-
- # To add a new fileset type, all we have to do is this:
- # set fileSetsTypesThing(tex) "tex"
- # lappend fileSetsTypes "tex"
- # If you create new types just add lines like that
-
- #===========================================================================
- # The support routines.
- #===========================================================================
- # Called from Alpha to get list of files for current file set.
- proc getCurrFileSet {} {
- global currFileSet
- return [getFileSet $currFileSet]
- }
-
- # Called from Alpha to get names. The first name returned is taken to
- # be the current fileset. For Alpha < 8.0, the list returned contains
- # the first item twice (as the first item, and then in its correct
- # position in the list). For Alpha >= 8.0 this silly behaviour has
- # been removed.
- proc getFileSetNames {{ordered 0}} {
- global gfileSets currFileSet gDirScan
- set perm {}
- if {!$ordered && $currFileSet != ""} {
- lappend perm $currFileSet
- }
- foreach n [lsort -ignore [array names gfileSets]] {
- if {!$ordered && ([info tclversion] >= 8.0) && $n == $currFileSet} {continue}
- if {[info exists gDirScan($n)]} {
- lappend temp $n
- } else {
- lappend perm $n
- }
- }
- if {[info exists temp]} {
- return [concat $perm - $temp]
- } else {
- return $perm
- }
- }
-
- #================================================================================
- # Edit a file from a fileset via list dialogs (no mousing around).
- #================================================================================
- proc editFile {} {
- global currFileSet modifiedVars gfileSetsType file::separator
-
- if {[catch {pickFileset "" {Fileset?} "list"} fset]} {return}
- set currFileSet $fset
- lappend modifiedVars currFileSet
-
- set ff [getFilesInSet $fset]
- foreach f $ff {
- lappend disp [file tail $f]
- }
- if {[catch {listpick -l -p {File?} [lsort -ignore $disp]} files]} {return}
- foreach res $files {
- set ind [lsearch $ff "\*${file::separator}$res"]
- if {$gfileSetsType($fset) == "ftp"} {
- ftpFilesetOpen $fset [lindex $ff $ind]
- } else {
- catch {generalOpenFileitem [lindex $ff $ind]}
- }
- }
- }
-
- # We only return TEXT files, since we don't want Alpha
- # manipulating the data fork of non-text files.
- proc getFileSet {fset} {
- global filesetmodeVars
- if {$filesetmodeVars(includeNonTextFiles)} {
- set fnames ""
- foreach f [getFilesInSet $fset] {
- if {[file isfile $f]} {
- getFileInfo $f a
- if {$a(type) == "TEXT"} {
- lappend fnames $f
- }
- }
- }
- return $fnames
- } else {
- return [getFilesInSet $fset]
- }
- }
-
- proc browseFileset {{fset ""}} {
- global tileLeft tileTop tileWidth errorHeight
-
- if {[catch {pickFileset $fset {Fileset?}} fset]} {return}
-
- foreach f [getFilesInSet $fset] {
- append text "\t[file tail $f]\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t∞$f\r"
- }
- new -n "* FileSet '$fset' Browser *" -g $tileLeft $tileTop 200 $errorHeight \
- -m Brws -info "(<cr> to go to file)\r-----\r$text\r"
- select [nextLineStart [nextLineStart [minPos]]] [nextLineStart [nextLineStart [nextLineStart [minPos]]]]
- message ""
- }
-
- # ◊◊◊◊ Basic procedures ◊◊◊◊ #
-
- namespace eval fileset {}
-
- # under development
- proc newFileset {} {
- global currFileSet gfileSetsType fileSetsTypesThing modifiedArrayElements
- foreach type {
- lappend dialog -n $type
- }
- set res [dialog::paged -pageproc fileset::page [lsort -ignore [array names fileSetsTypesThing]]]
-
- if {![string length $name]} return
-
- lappend modifiedArrayElements [list $name gfileSetsType]
- set gfileSetsType($name) $type
-
- set currFileSet $name
- filesetsJustChanged $type $name
- return $currFileSet
- }
-
- proc fileset::page {fset x y} {
- return [fileset::create$fset $x $y]
- }
-
- proc newFileset {{type ""}} {
- global currFileSet gfileSetsType fileSetsTypesThing modifiedArrayElements
- if {$type == ""} {
- set type [dialog::optionMenu "New fileset type?" [lsort -ignore [array names fileSetsTypesThing]] "fromDirectory"]
- }
- set name [eval ${type}CreateFileset]
-
- if {![string length $name]} return
-
- lappend modifiedArrayElements [list $name gfileSetsType]
- set gfileSetsType($name) $type
-
- set currFileSet $name
- filesetsJustChanged $type $name
- return $currFileSet
- }
-
-
- ##
- # -------------------------------------------------------------------------
- #
- # "filesetsJustChanged" --
- #
- # If we've added, deleted, modified a fileset, we call this procedure.
- # In most cases we must rebuild everything (due to limitations in Alpha),
- # but for 'procedural' filesets, we can just do the utilities menu.
- # -------------------------------------------------------------------------
- ##
- proc filesetsJustChanged {type name} {
- if {$type == "procedural"} {
- global filesetsNotInMenu modifiedVars
- if {[lsearch $filesetsNotInMenu $name] == -1} {
- lappend filesetsNotInMenu $name
- lappend modifiedVars filesetsNotInMenu
- }
- rebuildFilesetUtilsMenu
- } else {
- rebuildAllFilesets 1
- }
- }
-
- proc printFileset { {fset ""}} {
- if {[catch {pickFileset $fset "Print which Fileset?"} fset]} {return}
- foreach f [getFilesInSet $fset] {
- print $f
- }
- }
-
-
- proc deleteFileset { {fset ""} {yes 0} } {
- global fileSets gfileSets currFileSet fileSetsExtra gfileSetsType
- global filesetMenu subMenuFilesetInfo subMenuInfo filesetsNotInMenu
- global modifiedVars modifiedArrayElements
-
- if {[catch {pickFileset $fset "Delete which Fileset?"} fset]} {return}
- if {$currFileSet == $fset} {catch {set currFileSet System}}
-
- if {$yes || [dialog::yesno "Delete fileset \"$fset\"?"]} {
- catch {unset "fileSetsExtra($fset)"}
- catch {unset "gfileSetsType($fset)"}
- catch {unset "fileSets($fset)"}
- catch {unset "gfileSets($fset)"}
-
- lappend modifiedArrayElements \
- [list $fset gfileSetsType] [list $fset fileSetsExtra] \
- [list $fset gfileSets]
-
- set err [catch {removeFilesetFromMenu $fset}]
-
- if {[set l [lsearch -exact $filesetsNotInMenu $fset]] != -1} {
- set filesetsNotInMenu [lreplace $filesetsNotInMenu $l $l]
- lappend modifiedVars filesetsNotInMenu
- deleteMenuItem -m choose $fset
- deleteMenuItem -m hideFileset $fset
- return
- }
- if {$err} {
- # it's on a submenu or somewhere else so we just have
- # to do the lot!
- if {!$yes} { rebuildAllFilesets 1 }
- } else {
- deleteMenuItem -m choose $fset
- deleteMenuItem -m hideFileset $fset
- }
- }
- }
-
- proc removeFilesetFromMenu {fset} {
- global subMenuFilesetInfo subMenuInfo
- # find its menu:
- if {[info exists subMenuFilesetInfo($fset)]} {
- foreach m $subMenuFilesetInfo($fset) {
- # remove info about it's name
- if {[info exists subMenuInfo($m)]} {
- unset subMenuInfo($m)
- cache::add filesetMenuCache "eval" [list unset subMenuInfo($m)]
- }
- }
- set base [lindex $subMenuFilesetInfo($fset) 0]
- unset subMenuFilesetInfo($fset)
- cache::add filesetMenuCache "eval" [list unset subMenuFilesetInfo($fset)]
- cache::snippetRemove $fset
- # this will fail if it's on a submenu or if it isn't a menu at all
- deleteMenuItem -m $filesetMenu $base
- cache::add filesetMenuCache "eval" [list deleteMenuItem -m $filesetMenu $base]
- } else {
- # I think I do nothing
- }
-
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "pickFileset" --
- #
- # Ask the user for a/several filesets. If 'fset' is set, we just return
- # that (this avoids 'if {$fset != ""} { set fset [pick...] } constructs
- # everywhere). A prompt can be given, and a dialog type (either a
- # listpick, a pop-up menu, or a listpick with multiple selection), and
- # extra items can be added to the list if desired.
- # -------------------------------------------------------------------------
- ##
- proc pickFileset { fset {prompt Fileset?} {type "list"} {extras {}} } {
- global gfileSets currFileSet
- if { $fset != "" } { return $fset }
- switch -- $type {
- "popup" {
- set fset [eval [list prompt $prompt \
- $currFileSet "FileSet:"] [lsort -ignore [array names gfileSets]]]
- if {![info exists gfileSets($fset)]} { error "No such fileset" }
- return $fset
- }
- "list" {
- return [listpick -p $prompt -L $currFileSet \
- [lsort -ignore [concat $extras [array names gfileSets]]]]
- }
- "multilist" {
- return [listpick -p $prompt -l -L $currFileSet \
- [lsort -ignore [concat $extras [array names gfileSets]]]]
- }
- }
- }
-
- proc renameFileset {} {
- global fileSets gfileSets currFileSet fileSetsExtra gfileSetsType
- global fileSetsTypesThing modifiedArrayElements
-
- if {[catch {pickFileset "" {Fileset to rename?}} fset]} {return}
-
- set name [getline "Rename to:" $fset]
- if {![string length $name] || $name == $fset} return
-
- set gfileSets($name) $gfileSets($fset)
- set gfileSetsType($name) $gfileSetsType($fset)
- catch {set fileSets($name) $fileSets($fset)}
- catch {set fileSetsExtra($name) $fileSetsExtra($fset)}
-
- deleteFileset $fset 1
-
- lappend modifiedArrayElements [list $name gfileSets]
- lappend modifiedArrayElements [list $name gfileSetsType]
- lappend modifiedArrayElements [list $name fileSetsExtra]
-
- filesetsJustChanged $gfileSetsType($name) $name
- set currFileSet $name
- }
-
- proc updateCurrentFileset {} {
- global currFileSet
- updateAFileset $currFileSet
- }
-
- proc updateAFileset { {fset ""} } {
- if {[catch {pickFileset $fset} fset]} {return}
-
- global gfileSetsType fileSets subMenuFilesetInfo subMenuInfo
-
- set type $gfileSetsType($fset)
- catch {eval [list "${type}FilesetUpdate" $fset] }
- set m [makeFileSetAndMenu $fset 1]
- # we could rebuild the menu with this: but we don't
- cache::add filesetMenuCache "eval" $m
- if {[info exists subMenuFilesetInfo($fset)]} {
- # if the fileset already has a base menu, use that:
- foreach n $subMenuFilesetInfo($fset) {
- cache::add filesetMenuCache "variable" subMenuInfo($n)
- }
- cache::add filesetMenuCache "variable" subMenuFilesetInfo($n)
- }
- if {[info exists fileSets($fset)]} {
- cache::add filesetMenuCache "variable" fileSets($fset)
- }
- eval $m
- callFilesetUpdateProcedures $fset
- message "Done"
- }
-
- proc callFilesetUpdateProcedures { {fset ""} } {
- global filesetUpdateProcs gfileSetsType
- if { $fset == "" } {
- set types [array names filesetUpdateProcs]
- } else {
- set types $gfileSetsType($fset)
- }
-
- foreach l $types {
- if {[info exists filesetUpdateProcs($l)]} {
- foreach proc $filesetUpdateProcs($l) {
- uplevel \#0 $proc
- }
- }
- }
-
- }
-
- # ◊◊◊◊ Creation of basic fileset types ◊◊◊◊ #
-
- proc proceduralCreateFileset {} {
- global gfileSets gfileSetsType filesetsNotInMenu modifiedArrayElements
- set name [getline "Name for this fileset…"]
- if {![string length $name]} return
- set gfileSetsType($name) "procedural"
- set p procFileset[join $name ""]
- set gfileSets($name) $p
- addUserLine "\# procedure to list files in fileset '$name' on the fly"
- addUserLine "proc $p \{\} \{"
- addUserLine "\t"
- addUserLine "\}"
- lappend modifiedArrayElements [list $name gfileSets]
- lappend modifiedArrayElements [list $name gfileSetsType]
- if {[dialog::yesno "I've added a template for the procedure to your 'prefs.tcl'. Do you want to edit it now?"]} {
- global::editPrefsFile
- goto [maxPos]
- beep
- message "Make sure you 'load' the new procedure."
- }
- lappend filesetsNotInMenu $name
- return $name
- }
-
- # under development
- proc fileset::createfromDirectory {x y} {
- eval lappend dial \
- [dialog::edit "New fileset name:" $x y 20] \
- [dialog::edit "New fileset dir:" $x y 20] \
- [dialog::edit "File pattern:" $x y 20]
- }
-
- proc fromDirectoryCreateFileset {} {
- global gfileSets gfileSetsType fileSetsExtra
-
- set name [getFilesetDirectoryAndPattern]
- if {![string length $name]} return
- set filePatIgnore [getline "List of file patterns to ignore:" ""]
- if {$filePatIgnore != ""} {
- set fileSetsExtra($name) $filePatIgnore
- }
-
- set gfileSetsType($name) "fromDirectory"
-
- if {[dialog::yesno "Save new fileset?"]} {
- global modifiedArrayElements
- lappend modifiedArrayElements [list $name gfileSets]
- lappend modifiedArrayElements [list $name gfileSetsType]
- if {[info exists fileSetsExtra($name)]} {
- lappend modifiedArrayElements [list $name fileSetsExtra]
- }
- }
- return $name
- }
-
- proc getFilesetDirectoryAndPattern {} {
- global gfileSets fileSetsExtra
- set name [getline "New fileset name:" ""]
- if {![string length $name]} return
-
- set dir [get_directory -p "New fileset dir:"]
- if {![string length $dir]} return
-
- set filePat [getline "File pattern:" "*"]
- if {![string length $filePat]} return
-
- set gfileSets($name) [file join $dir $filePat]
- return $name
- }
-
- proc fromDirectoryFilesetUpdate {name} {
- # done on the fly so no need to update
- #global fileSets gfileSets
- #set fileSets($name) [glob -t TEXT -nocomplain "$gfileSets($name)"]
- }
-
- proc fromHierarchyCreateFileset {} {
- global gfileSets gfileSetsType
-
- set name [getFilesetDirectoryAndPattern]
- if {![string length $name]} return
-
- set gfileSetsType($name) "fromHierarchy"
- set depth [listpick -p "Depth of hierarchy?" -L 3 {1 2 3 4 5 6 7}]
- if { $depth == "" } {set depth 3}
-
- set gfileSets($name) [list $gfileSets($name) $depth]
-
- if {[dialog::yesno "Save new fileset?"]} {
- global modifiedArrayElements
- lappend modifiedArrayElements [list $name gfileSets] \
- [list $name gfileSetsType]
- }
- return $name
- }
-
- proc fromHierarchyFilesetUpdate {name} {
- fromHierarchyMakeFileSet $name 0
- }
-
- proc fromHierarchyMakeFileSetAndMenu {name andMenu} {
- global filesetTemp fileSets gfileSets
- set dir [file dirname [lindex $gfileSets($name) 0]]
- set patt [file tail [lindex $gfileSets($name) 0]]
- set depth [lindex $gfileSets($name) 1]
- # we make the menu as a string, but can bin it if we like
- set menu [menu::buildHierarchy [list $dir] $name filesetProc filesetTemp $patt $depth $name]
-
- # we need to construct the list of items
- set fileSets($name) {}
- if {[info exists filesetTemp]} {
- foreach n [array names filesetTemp] {
- lappend fileSets($name) $filesetTemp($n)
- }
- unset filesetTemp
- }
- return $menu
- }
-
- proc fromHierarchyFilesetSelected {fset menu item} {
- global gfileSets
- set dir [file dirname [lindex $gfileSets($fset) 0]]
- set ff [getFilesInSet $fset]
- if { $fset == $menu } {
- # it's top level
- if {[set match [lsearch $ff [file join ${dir} $item]]] >= 0} {
- autoUpdateFileset $fset
- generalOpenFileitem [lindex $ff $match]
- return
- }
- }
- # the following two are slightly cumbersome, but give us the best
- # chance of finding the correct file given any ambiguity (which can
- # certainly arise if file and directory names clash excessively).
- if {[set match [lsearch $ff [file join ${dir} ${menu} $item]]] >= 0} {
- autoUpdateFileset $fset
- generalOpenFileitem [lindex $ff $match]
- return
- }
- if {[set match [lsearch $ff [file join ${dir} * ${menu} $item]]] >= 0} {
- autoUpdateFileset $fset
- generalOpenFileitem [lindex $ff $match]
- return
- }
- error "Weird! Couldn't find it."
- }
-
-
- proc codewarriorCreateTagFile {} { return [alphaCreateTagFile] }
- proc thinkCreateTagFile {} { return [alphaCreateTagFile] }
-
- proc fromOpenWindowsCreateFileset {} {
- global gfileSets modifiedArrayElements
-
- set name [prompt "Create fileset containing current windows under what name?" "OpenWins"]
-
- set gfileSets($name) [winNames -f]
- lappend modifiedArrayElements [list $name gfileSets]
-
- return $name
- }
-
-
- # ◊◊◊◊ Menu procedures ◊◊◊◊ #
-
- ##
- # Global procedures to deal with the fact that Alpha can only have one
- # menu with each given name. This is only a problem in dealing with
- # user-defined menus such as fileset menus, tex-package menus, ...
- ##
-
- ##
- # -------------------------------------------------------------------------
- #
- # "makeFilesetSubMenu" --
- #
- # If desired this is the only procedure you need use --- it returns a menu
- # creation string, taking account of the unique name requirement and will
- # make sure your procedure 'proc' is called with the real menu name!
- # -------------------------------------------------------------------------
- ##
- proc makeFilesetSubMenu {fset name proc args} {
- if { [string length $proc] > 1 } {
- return [concat {Menu -m -n} [list [registerFilesetMenuName $fset $name $proc]] -p subMenuProc $args]
- } else {
- return [concat {Menu -m -n} [list [registerFilesetMenuName $fset $name]] $args]
- }
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "registerFilesetMenuName" --
- #
- # Call to ensure unique fileset submenu names. We just add spaces as
- # appropriate and keep track of everything for you! Filesets which have
- # multiple menus _must_ register the main menu first.
- # -------------------------------------------------------------------------
- ##
- proc registerFilesetMenuName {fset name {proc ""}} {
- global subMenuInfo subMenuFilesetInfo
- if { $fset == $name && [info exists subMenuFilesetInfo($fset)] } {
- # if the fileset already has a base menu, use that:
- foreach n $subMenuFilesetInfo($fset) {
- if { [string trimright $n] == $fset } {
- set base $n
- }
- unset subMenuInfo($n)
- }
- unset subMenuFilesetInfo($fset)
- }
- set original $name
- if {[info exists base]} {
- set name $base
- } else {
- # I add at least one space to _all_ hierarchical submenus now.
- # This is so I won't clash with any current or future modes
- # which should never normally add spaces themselves.
- append name " "
- while { [info exists subMenuInfo($name)] } {
- append name " "
- }
- }
-
- set subMenuInfo($name) [list "$fset" "$original" "$proc"]
- # build list of a fileset's menus
- lappend subMenuFilesetInfo($fset) "$name"
-
- return $name
- }
-
-
- proc realMenuName {name} {
- global subMenuInfo
- return [lindex $subMenuInfo($name) 1]
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "subMenuProc" --
- #
- # This procedure is implicitly used to deal with ensuring unique sub-menu
- # names. It calls the procedure you asked for, with the name of the menu
- # you think you're using.
- # -------------------------------------------------------------------------
- ##
- proc subMenuProc {menu item} {
- global subMenuInfo
- set l $subMenuInfo($menu)
- set realProc [lindex $l 2]
- if {[info commands $realProc] == ""} {catch "$realProc"}
- # try to call the proc with three arguments (fileset is 1st)
- if {[llength [info args $realProc]] == 2} {
- $realProc [lindex $l 1] "$item"
- } else {
- $realProc [lindex $l 0] [lindex $l 1] "$item"
- }
- }
-
-
- proc filesetMenuProc {menu item} {
- switch $item {
- "Edit File" {
- editFile
- return
- }
- "Help" {
- global HOME
- editMark [file join $HOME Help "Alpha Manual"] "File Sets" -r
- return
- }
- }
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "filesetProc" --
- #
- # Must be called by 'subMenuProc'
- # -------------------------------------------------------------------------
- ##
- proc filesetProc {fset menu item} {
- global gfileSetsType
- if {$fset != ""} {set m $fset} else { set m $menu}
- switch -- $gfileSetsType($m) {
- "fromDirectory" -
- "think" -
- "codewarrior" -
- "fromOpenWindows" {
- if {[catch {filesetBasicOpen $m $item}]} {
- if {[dialog::yesno "That file wasn't found. That fileset is probably out of date; do you want to rebuild it?"]} {
- updateAFileset $fset
- }
- }
- }
- "ftp" { ftpFilesetOpen $m $item }
- "default" {
- # try a type-specific method first
- set proc $gfileSetsType($m)FilesetSelected
- if {[info commands $proc] == "" && (![auto_load $proc])} {
- # if that failed then just hope it's an ordinary list
- if {![catch {filesetBasicOpen $m $item}]} {return}
- } else {
- if {[llength [info args $proc]] == 2} {
- if {![catch {eval [list $proc $menu $item]}]} {return}
- } else {
- if {![catch {eval [list $proc $fset $menu $item]}]} {return}
- }
- }
-
- if {[dialog::yesno "That file wasn't found. That fileset is probably out of date; do you want to rebuild it?"]} {
- updateAFileset $fset
- }
- }
- }
- }
-
- proc filesetBasicOpen { menu item } {
- global file::separator
- if {[set match [lsearch [getFilesInSet $menu] *${file::separator}$item]] >= 0} {
- autoUpdateFileset $menu
- generalOpenFileitem [lindex [getFilesInSet $menu] $match]
- return
- }
- error "file not found"
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "generalOpenFileitem" --
- #
- # Works around an alpha bug with aliases.
- # -------------------------------------------------------------------------
- ##
- proc generalOpenFileitem {file} {
- if {[file isfile $file]} {
- file::openAny $file
- } else {
- # is it an alias?
- if {[file type $file] == "unknown"} {
- getFileInfo $file a
- # is it a folder?
- if {$a(type) != "fdrp"} {
- file::openAny $file
- return
- }
- }
- global file::separator
- findFile "${file}${file::separator}"
- }
- }
-
- proc registerUpdateProcedure { type proc } {
- global filesetUpdateProcs
- lappend filesetUpdateProcs($type) $proc
- }
-
- proc filesetUtilsProc { menu item } {
- global filesetUtils gfileSetsType currFileSet
- if {[info exists filesetUtils($item)]} {
- # it's a utility
- set utilDesc $filesetUtils($item)
- set allowedTypes [lindex $utilDesc 0]
- if {[string match $allowedTypes $gfileSetsType($currFileSet)]} {
- return [eval [lindex $utilDesc 1]]
- } else {
- beep
- message "That utility can't be applied to the current file-set."
- return
- }
- } else {
- $item
- }
- }
- proc getFilesInSet {fset} {
- global gfileSets fileSetsTypesThing gfileSetsType
- switch -- $fileSetsTypesThing($gfileSetsType($fset)) {
- "list" {
- return $gfileSets($fset)
- }
- "glob" {
- global filesetmodeVars fileSetsExtra
- if {$filesetmodeVars(includeNonTextFiles)} {
- set l [glob -nocomplain "$gfileSets($fset)"]
- if {[info exists fileSetsExtra($fset)]} {
- foreach pat $fileSetsExtra($fset) {
- foreach f [glob -nocomplain [file join [file dirname "$gfileSets($fset)"] $pat]] {
- set i [lsearch $l $f]
- set l [lreplace $l $i $i]
- }
- }
- }
- return $l
- } else {
- set l [glob -t TEXT -nocomplain "$gfileSets($fset)"]
- if {[info exists fileSetsExtra($fset)]} {
- foreach pat $fileSetsExtra($fset) {
- foreach f [glob -t TEXT -nocomplain [file join [file dirname "$gfileSets($fset)"] $pat]] {
- set i [lsearch $l $f]
- set l [lreplace $l $i $i]
- }
- }
- }
- return $l
- }
- }
- "procedural" {
- return [$gfileSets($fset)]
- }
- "default" {
- global fileSets
- if {![info exists fileSets($fset)]} {
- # This means the menu was cached, but this info wasn't.
- # We calculate the set, and menu, and cache them
- # (since they're at the end of the file, they over-ride
- # what's there.
-
- # we rebuild the menu too
- eval [makeFileSetAndMenu $fset 1]
- cache::add filesetMenuCache "variable" fileSets($fset)
- }
- return $fileSets($fset)
- }
- }
- }
-
- proc makeFileSetAndMenu {name andMenu {use_cache 0}} {
- if {$use_cache} {
- set m [cache::snippetRead $name]
- if {$m != ""} {return $m}
- }
- global gfileSetsType fileSetsTypesThing
- message "Building ${name}..."
- set type $gfileSetsType($name)
- switch -- $fileSetsTypesThing($type) {
- "list" -
- "glob" {
- if {$andMenu} {
- set menu {}
- foreach m [getFilesInSet $name] {
- lappend menu "[file tail $m]&"
- }
- set m [makeFilesetSubMenu $name $name filesetProc [lsort -increasing $menu]]
- } else {
- return
- }
- }
- "procedural" {
- return
- }
- "default" {
- set m [${type}MakeFileSetAndMenu $name $andMenu]
-
- }
- }
- cache::snippetWrite $name $m
- return $m
- }
-
- proc filesetsSorted { order usedvar {use_cache 0}} {
- upvar $usedvar used
- global filesetmodeVars gfileSets gfileSetsType
- set sets {}
- foreach item $order {
- switch -- [lindex $item 0] {
- "-" {
- # add divider
- lappend sets "(-"
- continue
- }
- "*" {
- # add all the rest
- set subset {}
- foreach s [array names gfileSets] {
- if {![lcontains used $s]} {
- lappend subset $s
- lappend used $s
- }
- }
- foreach f [lsort $subset] {
- lappend sets [makeFileSetAndMenu $f 1 $use_cache]
- }
- }
- "pattern" {
- # find all which match a given pattern
- set patt [lindex $item 1]
- set subset {}
- foreach s [array names gfileSets] {
- if {![lcontains used $s]} {
- if {[string match $patt $s]} {
- lappend subset $s
- lappend used $s
- }
- }
- }
- foreach f [lsort $subset] {
- lappend sets [makeFileSetAndMenu $f 1 $use_cache]
- }
-
- }
- "submenu" {
- # add a submenu with name following and sub-order
- set name [lindex $item 1]
- set suborder [lrange $item 2 end]
- # we make kind of a pretend fileset here.
- set subsets [filesetsSorted $suborder used]
- if { $subsets != "" } {
- lappend sets [makeFilesetSubMenu $name $name filesetProc $subsets]
- }
- }
- "default" {
- set subset {}
- foreach s [array names gfileSets] {
- if {[lcontains item $gfileSetsType($s)] && ![lcontains used $s]} {
- lappend subset $s
- lappend used $s
- }
- }
- foreach f [lsort $subset] {
- lappend sets [makeFileSetAndMenu $f 1 $use_cache]
- }
- }
- }
-
- }
- # remove multiple and leading, trailing '-' in case there were gaps
- regsub -all {\(-( \(-)+} $sets {(-} sets
- while { [lindex $sets 0] == "(-" } { set sets [lrange $sets 1 end] }
- set l [expr {[llength $sets] -1}]
- if { [lindex $sets $l] == "(-" } { set sets [lrange $sets 0 [incr l -1]] }
-
- return $sets
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "rebuildFilesetMenu" --
- #
- # Reads the fileset menu from the cache if it exists. This speeds up
- # start-up by quite a bit.
- # -------------------------------------------------------------------------
- ##
- proc rebuildFilesetMenu {} {
- message "Building filesets..."
- if {[cache::exists filesetMenuCache]} {
- global subMenuFilesetInfo subMenuInfo fileSets
- cache::read filesetMenuCache
- rebuildFilesetUtilsMenu
- callFilesetUpdateProcedures
- } else {
- rebuildAllFilesets 1
- }
-
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "zapAndBuildFilesets" --
- #
- # This does a complete rebuild of all information. The problem is that
- # the names of menus may actually change (spaces added/deleted). This is
- # not a problem for the fileset menu, but is a problem for any filesets
- # which have been added to other menus, since they won't know that they
- # need to be rebuilt.
- # -------------------------------------------------------------------------
- ##
- proc zapAndBuildFilesets {} {
- global subMenuInfo subMenuFilesetInfo
- unset subMenuInfo
- unset subMenuFilesetInfo
- rebuildAllFilesets
- }
-
- proc rebuildAllFilesets { {use_cache 0} } {
- global gfileSets filesetMenu filesetSortOrder
- global filesetmodeVars filesetsNotInMenu fileSets
- message "Rebuilding filesets menu…"
-
- if {$filesetmodeVars(sortFilesetsByType)} {
- # just make file-sets for those we don't want in the menu
- if {!$use_cache} {
- foreach f $filesetsNotInMenu {
- makeFileSetAndMenu $f 0
- }
- }
- set used $filesetsNotInMenu
- set sets [filesetsSorted $filesetSortOrder used $use_cache]
- } else {
- foreach f [lsort [array names gfileSets]] {
- set doMenu [expr {![lcontains filesetsNotInMenu $f]}]
- set menu [makeFileSetAndMenu $f $doMenu $use_cache]
- if {$doMenu && [llength $menu]} {
- lappend sets $menu
- }
- }
- }
-
- regsub -all {[-][nm]} $sets "" names
- foreach nn $names {
- lappend names_ [string trimright [lindex $names 1]]
- }
- set names $names_
-
- # cache the fileset menu
- set m [list Menu -m -n $filesetMenu -p filesetMenuProc \
- [concat {{/'Edit File…} {Menu -n Utilities {}}} "Help" \
- "(-" $sets]]
- cache::create filesetMenuCache
- cache::add filesetMenuCache "eval" $m [list insertMenu $filesetMenu]
- global subMenuFilesetInfo subMenuInfo
- cache::add filesetMenuCache "variable" subMenuFilesetInfo subMenuInfo fileSets
- eval $m
-
- rebuildFilesetUtilsMenu
- callFilesetUpdateProcedures
-
- message ""
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "rebuildSomeFilesetMenu" --
- #
- # If given '*' rebuild the entire menu, else rebuild only those types
- # given. This is generally useful to avoid excessive rebuilding when
- # flags are adjusted
- # -------------------------------------------------------------------------
- ##
- proc rebuildSomeFilesetMenu {args} {
- rebuildAllFilesets
- }
-
- proc rebuildFilesetUtilsMenu {} {
- global gfileSets filesetUtils
-
- Menu -n "Utilities" -p filesetUtilsProc [concat \
- "newFileset…" \
- "deleteFileset…" \
- "printFileset…" \
- "<S<EupdateAFileset…" \
- "<SupdateCurrentFileset" \
- "<S<EzapAndBuildFilesets" \
- "<SrebuildAllFilesets" \
- [list [menu::makeFlagMenu choose list currFileSet]] \
- [list [list Menu -n hideFileset -m -p hideShowFileset [lsort [array names gfileSets]]]] \
- [list [menu::makeFlagMenu filesetFlags array filesetmodeVars]] \
- "(-" \
- "/T<I<OfindTag" \
- "createTagFile" \
- "(-" \
- [lsort [array names filesetUtils]] \
- ]
-
- filesetUtilsMarksTicks
- }
-
- proc rebuildSimpleFilesetMenus {} {
- global gfileSets fileSetsTypesThing
- eval [menu::makeFlagMenu choose list currFileSet]
- Menu -n hideFileset -m -p hideShowFileset [lsort [array names gfileSets]]
- filesetUtilsMarksTicks
- }
-
- proc hideShowFileset {menu item} {
- global filesetsNotInMenu filesetMenu
- if {[lcontains filesetsNotInMenu $item]} {
- global gfileSetsType
- if {$gfileSetsType($item) == "procedural"} {
- alertnote "Sorry, procedural filesets are completely dynamic and cannot appear in menus."
- return
- }
- set idx [lsearch $filesetsNotInMenu $item]
- set filesetsNotInMenu [lreplace $filesetsNotInMenu $idx $idx]
- markMenuItem -m hideFileset $item off
- # would be better if we could just insert it
- rebuildAllFilesets 1
- } else {
- lappend filesetsNotInMenu $item
- markMenuItem -m hideFileset $item on
- if {[catch {removeFilesetFromMenu $item}]} {
- rebuildAllFilesets 1
- }
- }
- global modifiedVars
- lappend modifiedVars filesetsNotInMenu
- }
-
- proc filesetUtilsMarksTicks {} {
- global filesetsNotInMenu
-
- foreach name $filesetsNotInMenu {
- markMenuItem -m hideFileset $name on
- }
-
- }
-
-
- # Called in response to user changing filesets from the fileset menu.
- proc changeFileSet {item} {
- global currFileSet tagFile
- # Bring in the tags file for this fileset
- set fname [tagFileName]
- if {[file exists $fname]} {
- if {[dialog::yesno "Use tag file from folder \"$dir\" ?"]} {
- set tagFile $fname
- }
- }
- }
-
- proc autoUpdateFileset { name } {
- global currFileSet filesetmodeVars modifiedVars
- if {$filesetmodeVars(autoAdjustFileset)} {
- set currFileSet $name
- lunion modifiedVars currFileSet
- }
- }
-
-
- # ◊◊◊◊ Utility procs ◊◊◊◊ #
-
- proc isWindowInFileset { {win "" } {type ""} } {
- if {$win == ""} { set win [win::Current] }
- global currFileSet gfileSets gfileSetsType
-
- if { $type == "" } {
- set okSets [array names gfileSets]
- } else {
- set okSets {}
- foreach s [array names gfileSets] {
- if { $gfileSetsType($s) == $type } {
- lappend okSets $s
- }
- }
- }
-
- if {[array exists gfileSets]} {
- if {[lsearch -exact $okSets $currFileSet] != -1 } {
- # check current fileset
- if {[lsearch -exact [getFilesInSet $currFileSet] $win] != -1 } {
- # we're set, it's in this fileset
- return $currFileSet
- }
- }
-
- # check other fileset
- foreach fset $okSets {
- if {[lsearch -exact [getFilesInSet $fset] $win] != -1 } {
- # we're set, it's in this project
- return $fset
- }
- }
- }
- return ""
-
- }
-
-
-
- ##
- # -------------------------------------------------------------------------
- #
- # "iterateFileset" --
- #
- # Utility procedure to iterate over all files in a project, calling some
- # predefined function '$fn' for each member of project '$proj'. The
- # results of such a call are passed to '$resfn' if given. Finally "done"
- # is passed to 'resfn'.
- #
- # -------------------------------------------------------------------------
- ##
- proc iterateFileset { proj fn { resfn \# } } {
- global gfileSets gfileSetsType
- eval $resfn "first"
-
- set check [expr {![catch {$gfileSetsType($proj)IterateCheck check}]}]
-
- foreach ff [getFileSet $proj] {
- if { $check && [$gfileSetsType($proj)IterateCheck $proj $ff] } {
- continue
- }
- set res [eval $fn [list $ff]]
- eval $resfn [list $res]
- }
-
- if {$check} {
- catch {$gfileSetsType($proj)IterateCheck done}
- }
-
- eval $resfn "done"
-
- }
-
- # ◊◊◊◊ Tags ◊◊◊◊ #
-
- if {![string length [info commands alphaFindTag]]} {
- rename findTag alphaFindTag
- rename createTagFile alphaCreateTagFile
- }
-
- proc tagFileName {} {
- global gfileSets currFileSet
- return [file join [file dirname [car $gfileSets($currFileSet)]] "[join ${currFileSet}]TAGS"]
- }
-
- proc findTag {} {
- global gfileSetsType currFileSet
- # try a type-specific method first
- if {[catch {$gfileSetsType($currFileSet)FindTag}]} {
- alphaFindTag
- }
- }
-
- proc createTagFile {} {
- global gfileSetsType currFileSet tagFile modifiedVars
- set tagFile [tagFileName]
- lappend modifiedVars tagFile
-
- # try a type-specific method first
- if {[catch {$gfileSetsType($currFileSet)CreateTagFile}]} {
- alphaCreateTagFile
- }
- }
-
- # ◊◊◊◊ Utils ◊◊◊◊ #
-
-
- proc dirtyFileset { fset } {
- foreach f [getFilesInSet $fset] {
- if { ![catch {getWinInfo -w $f arr}] && $arr(dirty)} { return 1 }
- }
- return 0
- }
-
- proc saveEntireFileset { fset } {
- foreach f [getFilesInSet $fset] {
- if { ![catch {getWinInfo -w $f arr}] && $arr(dirty)} {
- bringToFront $f
- save
- }
- }
- }
-
- proc closeEntireFileset { {fset ""} } {
- if {[catch {pickFileset $fset "Close which fileset?" "popup"} fset]} {return}
-
- foreach f [getFilesInSet $fset] {
- if {![catch {getWinInfo -w $f arr}]} {
- bringToFront $f
- killWindow
- }
- }
- }
-
- proc fileToAlpha {f} {
- if {[file isfile $f] && ([getFileType $f] == "TEXT") && ([getFileSig $f] != "ALFA")} {
- message "Converting $f"
- setFileInfo $f creator ALFA
- }
- }
-
- proc filesetToAlpha {} {
- if {[catch {pickFileset "" {Convert all files from which fileset?} "popup"} fset]} {return}
- iterateFileset $fset fileToAlpha
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "replaceInFileset" --
- #
- # Quotes things correctly so searches work, and adds a check on
- # whether there are any windows.
- # -------------------------------------------------------------------------
- ##
- proc replaceInFileset {} {
- global gfileSets win::NumDirty
- set how [dialog::optionMenu "Search type:" \
- [list "Textual replace" "Case-independent textual replace" \
- "Regexp replace" "Case-independent regexp replace"] "" 1]
- set from [prompt "Search string:" [searchString]]
- searchString $from
- if {$how < 2} {set from [quote::Regfind $from]}
-
- set to [prompt "Replace string:" [replaceString]]
- replaceString $to
- if {$how < 2} {set to [quote::Regsub $to]}
- if {[catch {regsub -- $from "$from" $to dummy} err]} {
- alertnote "Regexp compilation problems: $err"
- return
- }
- set fsets [pickFileset "" "Which filesets?" "multilist"]
-
- if {${win::NumDirty}} {
- if {[buttonAlert "Save all windows?" "Yes" "Cancel"] != "Yes"} return
- saveAll
- }
-
- set cid [scancontext create]
- set changes 0
- if {$how & 1} {
- set case "-nocase"
- } else {
- set case "--"
- }
-
- scanmatch $case $cid $from {set matches($f) 1 ;incr changes}
- foreach fset $fsets {
- foreach f [getFileSet $fset] {
- if {![catch {set fid [open $f]}]} {
- message "Looking at '[file tail $f]'"
- scanfile $cid $fid
- close $fid
- }
- }
- }
-
- scancontext delete $cid
-
- foreach f [array names matches] {
- message "Modifying ${f}…"
- set cid [open $f "r"]
- if {[regsub -all $case $from [read $cid] $to out]} {
- set ocid [open $f "w+"]
- puts -nonewline $ocid $out
- close $ocid
- }
- close $cid
- }
-
- eval file::revertThese [array names matches]
- message "Replaced $changes instances"
- }
-
- proc openEntireFileset {} {
- set fset [pickFileset "" "Open which fileset?" "popup"]
-
- # we use our iterator in case there's something special to do
- iterateFileset $fset "edit -c -w"
- }
-
- proc openFilesetFolder {} {
- global gfileSets
- set fset [pickFileset "" "Open which fileset's folder?" "popup"]
- if {[llength [list $gfileSets($fset)]] == 1 && [file isdirectory [set dir [file dirname $gfileSets($fset)]]]} {
- openFolder $dir
- } else {
- alertnote "Fileset not connected to a folder."
- }
- }
-
- proc stuffFileset {} {
- global gfileSetsType gfileSets
- set fset [pickFileset "" "Which fileset shall I stuff?" "popup"]
- if {[string length $fset]} {
- if { $gfileSetsType($fset) == "fromDirectory" && \
- [dialog::yesno "Stuff entire directory?"]} {
- app::launchFore DStf
- regexp {ZZ(.)ZZ} [file join ZZ ZZ] "" separator
- sendOpenEvent reply 'DStf' "[file dirname $gfileSets($fset)]${separator}"
- } else {
- app::launchFore DStf
- eval sendOpenEvents 'DStf' [getFilesInSet $fset]
- }
- sendQuitEvent 'DStf'
- }
- }
-
- proc filesetRememberOpenClose { file } {
- global fileset_openorclosed
- set fileset_openorclosed [list "$file" [lsearch -exact [winNames -f] $file]]
- }
-
- proc filesetRevertOpenClose { file } {
- global fileset_openorclosed
- if { [lindex $fileset_openorclosed 0] == "$file" } {
- if { [lindex $fileset_openorclosed 1] < 0 } {
- killWindow
- }
- }
- catch {unset fileset_openorclosed}
- }
-
- proc wordCountFileset {} {
- global currFileSet
- iterateFileset $currFileSet wordCountProc filesetUtilWordCount
- }
-
- proc filesetUtilWordCount {count} {
- global fs_ccount fs_wcount fs_lcount
- switch $count {
- "first" {
- set fs_ccount 0
- set fs_wcount 0
- set fs_lcount 0
- }
- "done" {
- alertnote "There were $fs_ccount lines, $fs_wcount words and $fs_lcount chars"
- unset fs_ccount fs_wcount fs_lcount
- }
- default {
- incr fs_ccount [lindex $count 2]
- incr fs_wcount [lindex $count 1]
- incr fs_lcount [lindex $count 0]
- }
- }
- }
-
-
- ##
- # -------------------------------------------------------------------------
- #
- # "wordCountProc" --
- #
- # Completely new proc which does the same as the old one
- # without opening lots of windows.
- # *Very* memory comsuming for large files, though.
- # But I think the old one was equally memeory consuming.
- #
- # Ok, this is not exactly a bug fix. It's a IMHO better option.
- #
- # -------------------------------------------------------------------------
- ##
-
- proc wordCountProc {file} {
- message "Counting [file tail $file]…"
- set fid [open $file r]
- set filecont [read $fid]
- close $fid
- if {[regexp {\n\r} $filecont]} {
- set newln "\n\r"
- } elseif {[regexp {\n} $filecont]} {
- set newln "\n"
- } else {
- set newln "\r"
- }
- set lines [expr {[regsub -all -- $newln $filecont " " filecont] + 1}]
- set chars [string length $filecont]
- regsub -all {[!=;.,\(\#\=\):\{\"\}]} $filecont " " filecont
- set words [llength $filecont]
- return "$chars $words $lines"
- }
-
-
- # ◊◊◊◊ From search dialog ◊◊◊◊ #
-
- proc findNewFileset {} {
- return [newFileset]
- }
-
-
- proc findNewDirectory {} {
- global gfileSets currFileSet gfileSetsType gDirScan
-
- set dir [get_directory -p "Scan which folder?"]
- if {![string length $dir]} return
-
- set filePat {*}
- set name [file tail $dir]
-
- set gfileSets($name) [file join $dir $filePat]
- set gDirScan($name) 1
- set gfileSetsType($name) "fromDirectory"
- set currFileSet $name
- updateCurrentFileset
- return $name
- }
-
- # Should be last so all filesets make it in.
- rebuildFilesetMenu
-
-
-
-
-
-
-
-
-